home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 2 / Amiga Tools 2.iso / tools / jade / src / housekeeping.c < prev    next >
C/C++ Source or Header  |  1995-03-09  |  14KB  |  528 lines

  1. /* housekeeping.c -- Generally editor fiddly stuff
  2.    Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>
  3.  
  4.    This file is part of Jade.
  5.  
  6.    Jade is free software; you can redistribute it and/or modify it
  7.    under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2, or (at your option)
  9.    any later version.
  10.  
  11.    Jade is distributed in the hope that it will be useful, but
  12.    WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.     See the
  14.    GNU General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU General Public License
  17.    along with Jade; see the file COPYING.  If not, write to
  18.    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #include "jade.h"
  21. #include "jade_protos.h"
  22.  
  23. _PR void adjust_marks_add_x(TX *, long, long, long);
  24. _PR void adjust_marks_sub_x(TX *, long, long, long);
  25. _PR void adjust_marks_add_y(TX *, long, long);
  26. _PR void adjust_marks_sub_y(TX *, long, long);
  27. _PR void adjust_marks_split_y(TX *, long, long);
  28. _PR void adjust_marks_join_y(TX *, long, long);
  29. _PR void resync_xy(VW *);
  30. _PR void set_start_col(VW *, long);
  31. _PR void set_start_line(VW *, long);
  32. _PR void reset_all_views(TX *);
  33.  
  34. /* The next few routines deal with updating the various references to
  35.    coordinates throughout the views after chunks have been deleted and
  36.    inserted.  */
  37.  
  38. void
  39. adjust_marks_add_x(TX *tx, long addx, long xpos, long ypos)
  40. {
  41.     VW *thisvw;
  42.     Mark *thismark;
  43.  
  44. #define UPD(x,y)                \
  45.     do {                    \
  46.     if((y == ypos) && (x >= xpos))        \
  47.         x += addx;                \
  48.     } while(0)
  49.  
  50.     for(thisvw = view_chain; thisvw; thisvw = thisvw->vw_Next)
  51.     {
  52.     if(thisvw->vw_Tx == tx)
  53.     {
  54.         UPD(thisvw->vw_CursorPos.pos_Col, thisvw->vw_CursorPos.pos_Line);
  55.             if(!(thisvw->vw_Flags & VWFF_RECTBLOCKS))
  56.         {
  57.         UPD(thisvw->vw_BlockS.pos_Col, thisvw->vw_BlockS.pos_Line);
  58.         UPD(thisvw->vw_BlockE.pos_Col, thisvw->vw_BlockE.pos_Line);
  59.         }
  60.     }
  61.     }
  62.     for(thismark = tx->tx_MarkChain; thismark; thismark = thismark->mk_Next)
  63.     {
  64.     UPD(VPOS(thismark->mk_Pos).pos_Col, VPOS(thismark->mk_Pos).pos_Line);
  65.     }
  66.     UPD(tx->tx_SavedCPos.pos_Col, tx->tx_SavedCPos.pos_Line);
  67.     UPD(tx->tx_SavedWPos.pos_Col, tx->tx_SavedWPos.pos_Line);
  68.     UPD(tx->tx_SavedBlockPos[0].pos_Col, tx->tx_SavedBlockPos[0].pos_Line);
  69.     UPD(tx->tx_SavedBlockPos[1].pos_Col, tx->tx_SavedBlockPos[1].pos_Line);
  70. #if 1
  71.     if((tx->tx_ModStart.pos_Line == ypos) && (tx->tx_ModStart.pos_Col > xpos))
  72.     tx->tx_ModStart.pos_Col += addx;
  73. #else
  74.     UPD(tx->tx_ModStart.pos_Col, tx->tx_ModStart.pos_Line);
  75. #endif
  76.     UPD(tx->tx_ModEnd.pos_Col, tx->tx_ModEnd.pos_Line);
  77.  
  78. #undef UPD
  79. }
  80.  
  81. void
  82. adjust_marks_sub_x(TX *tx, long subx, long xpos, long ypos)
  83. {
  84.     VW *thisvw;
  85.     Mark *thismark;
  86.  
  87. #define UPD(x,y)                \
  88.     do {                    \
  89.     if((y == ypos) && (x >= xpos))        \
  90.     {                    \
  91.         if((x -= subx) < xpos)        \
  92.         x = xpos;            \
  93.     }                    \
  94.     } while(0)
  95.  
  96.     for(thisvw = view_chain; thisvw; thisvw = thisvw->vw_Next)
  97.     {
  98.     if(thisvw->vw_Tx == tx)
  99.     {
  100.         UPD(thisvw->vw_CursorPos.pos_Col, thisvw->vw_CursorPos.pos_Line);
  101.             if(!(thisvw->vw_Flags & VWFF_RECTBLOCKS))
  102.         {
  103.         UPD(thisvw->vw_BlockS.pos_Col, thisvw->vw_BlockS.pos_Line);
  104.         UPD(thisvw->vw_BlockE.pos_Col, thisvw->vw_BlockE.pos_Line);
  105.         }
  106.     }
  107.     }
  108.     for(thismark = tx->tx_MarkChain; thismark; thismark = thismark->mk_Next)
  109.     {
  110.     UPD(VPOS(thismark->mk_Pos).pos_Col, VPOS(thismark->mk_Pos).pos_Line);
  111.     }
  112.     UPD(tx->tx_SavedCPos.pos_Col, tx->tx_SavedCPos.pos_Line);
  113.     UPD(tx->tx_SavedWPos.pos_Col, tx->tx_SavedWPos.pos_Line);
  114.     UPD(tx->tx_SavedBlockPos[0].pos_Col, tx->tx_SavedBlockPos[0].pos_Line);
  115.     UPD(tx->tx_SavedBlockPos[1].pos_Col, tx->tx_SavedBlockPos[1].pos_Line);
  116.  
  117.     UPD(tx->tx_ModStart.pos_Col, tx->tx_ModStart.pos_Line);
  118. #if 1
  119.     if((tx->tx_ModEnd.pos_Line == ypos) && (tx->tx_ModEnd.pos_Col > xpos))
  120.     {
  121.     if((tx->tx_ModEnd.pos_Col -= subx) < xpos)
  122.         tx->tx_ModEnd.pos_Col = xpos;
  123.     }
  124. #else
  125.     UPD(tx->tx_ModEnd.pos_Col, tx->tx_ModEnd.pos_Line);
  126. #endif
  127.  
  128. #undef UPD
  129. }
  130.  
  131. /*
  132.  * Whole lines only please
  133.  */
  134. void
  135. adjust_marks_add_y(TX *tx, long addy, long ypos)
  136. {
  137.     VW *thisvw;
  138.     Mark *thismark;
  139.  
  140. #define UPD(y)                    \
  141.     do {                    \
  142.     if(y >= ypos)                \
  143.         y += addy;                \
  144.     } while(0)
  145.  
  146.     for(thisvw = view_chain; thisvw; thisvw = thisvw->vw_Next)
  147.     {
  148.     if(thisvw->vw_Tx == tx)
  149.     {
  150.         UPD(thisvw->vw_CursorPos.pos_Line);
  151.         UPD(thisvw->vw_BlockS.pos_Line);
  152.         UPD(thisvw->vw_BlockE.pos_Line);
  153.         if(thisvw != curr_vw)
  154.         UPD(thisvw->vw_StartLine);
  155.     }
  156.     }
  157.     for(thismark = tx->tx_MarkChain; thismark; thismark = thismark->mk_Next)
  158.     {
  159.     UPD(VPOS(thismark->mk_Pos).pos_Line);
  160.     }
  161.     UPD(tx->tx_SavedCPos.pos_Line);
  162.     UPD(tx->tx_SavedWPos.pos_Line);
  163.     UPD(tx->tx_SavedBlockPos[0].pos_Line);
  164.     UPD(tx->tx_SavedBlockPos[1].pos_Line);
  165.  
  166. #if 0
  167. #if 1
  168.     if(tx->tx_ModStart.pos_Line > ypos)
  169.     tx->tx_ModStart.pos_Line += addy;
  170. #else
  171.     UPD(tx->tx_ModStart.pos_Line);
  172. #endif
  173.     UPD(tx->tx_ModEnd.pos_Line);
  174. #endif
  175.  
  176. #undef UPD
  177. }
  178.  
  179. /*
  180.  * Whole lines only please
  181.  */
  182. void
  183. adjust_marks_sub_y(TX *tx, long suby, long ypos)
  184. {
  185.     VW *thisvw;
  186.     Mark *thismark;
  187.  
  188. #define UPD(y)                    \
  189.     do {                    \
  190.     if(y > ypos)                \
  191.     {                    \
  192.         if((y -= suby) < ypos)        \
  193.         y = ypos;            \
  194.     }                    \
  195.     } while(0)
  196.  
  197. #define UPD2(x,y)                \
  198.     if(y >= ypos)                \
  199.     {                        \
  200.     if((y -= suby) < ypos)            \
  201.     {                    \
  202.         y = ypos;                \
  203.         x = 0;                \
  204.     }                    \
  205.     } while(0)
  206.  
  207.     for(thisvw = view_chain; thisvw; thisvw = thisvw->vw_Next)
  208.     {
  209.     if(thisvw->vw_Tx == tx)
  210.     {
  211.         UPD2(thisvw->vw_CursorPos.pos_Col, thisvw->vw_CursorPos.pos_Line);
  212.             if(thisvw->vw_Flags & VWFF_RECTBLOCKS)
  213.         {
  214.         UPD(thisvw->vw_BlockS.pos_Line);
  215.         UPD(thisvw->vw_BlockE.pos_Line);
  216.         }
  217.             else
  218.         {
  219.                 UPD2(thisvw->vw_BlockS.pos_Col, thisvw->vw_BlockS.pos_Line);
  220.                 UPD2(thisvw->vw_BlockE.pos_Col, thisvw->vw_BlockE.pos_Line);
  221.         }
  222.         if(thisvw != curr_vw)
  223.         UPD(thisvw->vw_StartLine);
  224.     }
  225.     }
  226.     for(thismark = tx->tx_MarkChain; thismark; thismark = thismark->mk_Next)
  227.     {
  228.     UPD2(VPOS(thismark->mk_Pos).pos_Col, VPOS(thismark->mk_Pos).pos_Line);
  229.     }
  230.     UPD2(tx->tx_SavedCPos.pos_Col, tx->tx_SavedCPos.pos_Line);
  231.     UPD2(tx->tx_SavedWPos.pos_Col, tx->tx_SavedWPos.pos_Line);
  232.     UPD2(tx->tx_SavedBlockPos[0].pos_Col, tx->tx_SavedBlockPos[0].pos_Line);
  233.     UPD2(tx->tx_SavedBlockPos[1].pos_Col, tx->tx_SavedBlockPos[1].pos_Line);
  234.  
  235.     UPD2(tx->tx_ModStart.pos_Col, tx->tx_ModStart.pos_Line);
  236. #if 1
  237.     if(tx->tx_ModEnd.pos_Line > ypos)
  238.     {
  239.     if((tx->tx_ModEnd.pos_Line -= suby) < ypos)
  240.     {
  241.         tx->tx_ModEnd.pos_Line = ypos;
  242.         tx->tx_ModEnd.pos_Col = 0;
  243.     }
  244.     }
  245. #else
  246.     UPD2(tx->tx_ModEnd.pos_Col, tx->tx_ModEnd.pos_Line);
  247. #endif
  248.  
  249. #undef UPD
  250. #undef UPD2
  251. }
  252.  
  253. /*
  254.  * Use when splitting a line into 2, cursor should be at position of split
  255.  */
  256. void
  257. adjust_marks_split_y(TX *tx, long xpos, long ypos)
  258. {
  259.     VW *thisvw;
  260.     Mark *thismark;
  261.  
  262. #define UPD(y)                    \
  263.     do {                    \
  264.     if(y > ypos)                \
  265.         y++;                \
  266.     } while(0)
  267.  
  268. #define UPD2(x,y)                \
  269.     do {                    \
  270.     if((y == ypos) && (x >= xpos))        \
  271.     {                    \
  272.         x -= xpos;                \
  273.         y++;                \
  274.     }                    \
  275.     else if(y > ypos)            \
  276.         y++;                \
  277.     } while(0)
  278.  
  279.     for(thisvw = view_chain; thisvw; thisvw = thisvw->vw_Next)
  280.     {
  281.     if(thisvw->vw_Tx == tx)
  282.     {
  283.         UPD2(thisvw->vw_CursorPos.pos_Col, thisvw->vw_CursorPos.pos_Line);
  284.             if(thisvw->vw_Flags & VWFF_RECTBLOCKS)
  285.         {
  286.         UPD(thisvw->vw_BlockS.pos_Line);
  287.         UPD(thisvw->vw_BlockE.pos_Line);
  288.         }
  289.             else
  290.         {
  291.                 UPD2(thisvw->vw_BlockS.pos_Col, thisvw->vw_BlockS.pos_Line);
  292.                 UPD2(thisvw->vw_BlockE.pos_Col, thisvw->vw_BlockE.pos_Line);
  293.         }
  294.         if(thisvw != curr_vw)
  295.         UPD(thisvw->vw_StartLine);
  296.     }
  297.     }
  298.     for(thismark = tx->tx_MarkChain; thismark; thismark = thismark->mk_Next)
  299.     {
  300.     UPD2(VPOS(thismark->mk_Pos).pos_Col, VPOS(thismark->mk_Pos).pos_Line);
  301.     }
  302.     UPD2(tx->tx_SavedCPos.pos_Col, tx->tx_SavedCPos.pos_Line);
  303.     UPD2(tx->tx_SavedWPos.pos_Col, tx->tx_SavedWPos.pos_Line);
  304.     UPD2(tx->tx_SavedBlockPos[0].pos_Col, tx->tx_SavedBlockPos[0].pos_Line);
  305.     UPD2(tx->tx_SavedBlockPos[1].pos_Col, tx->tx_SavedBlockPos[1].pos_Line);
  306.  
  307. #if 1
  308.     if((tx->tx_ModStart.pos_Line == ypos) && (tx->tx_ModStart.pos_Col > xpos))
  309.     {
  310.     tx->tx_ModStart.pos_Col -= xpos;
  311.     tx->tx_ModStart.pos_Line++;
  312.     }
  313.     else if(tx->tx_ModStart.pos_Line > ypos)
  314.     tx->tx_ModStart.pos_Line++;
  315. #else
  316.     UPD2(tx->tx_ModStart.pos_Col, tx->tx_ModStart.pos_Line);
  317. #endif
  318.     UPD2(tx->tx_ModEnd.pos_Col, tx->tx_ModEnd.pos_Line);
  319.  
  320. #undef UPD
  321. #undef UPD2
  322. }
  323.  
  324. /*
  325.  * Use when compacting 2 adjacent lines into one
  326.  */
  327. void
  328. adjust_marks_join_y(TX *tx, long xpos, long ypos)
  329. {
  330.     VW *thisvw;
  331.     Mark *thismark;
  332.  
  333. #define UPD(y)                    \
  334.     do {                    \
  335.     if(y > ypos)                \
  336.         y--;                \
  337.     } while(0)
  338.  
  339. #define UPD2(x,y)                \
  340.     do {                    \
  341.     if(y > ypos)                \
  342.     {                    \
  343.         if(y == ypos + 1)            \
  344.         {                    \
  345.         x += xpos;            \
  346.         y--;                \
  347.         }                    \
  348.     }                    \
  349.     } while(0)
  350.  
  351.     for(thisvw = view_chain; thisvw; thisvw = thisvw->vw_Next)
  352.     {
  353.     if(thisvw->vw_Tx == tx)
  354.     {
  355.         UPD2(thisvw->vw_CursorPos.pos_Col, thisvw->vw_CursorPos.pos_Line);
  356.             if(thisvw->vw_Flags & VWFF_RECTBLOCKS)
  357.         {
  358.         UPD(thisvw->vw_BlockS.pos_Line);
  359.         UPD(thisvw->vw_BlockE.pos_Line);
  360.         }
  361.             else
  362.         {
  363.                 UPD2(thisvw->vw_BlockS.pos_Col, thisvw->vw_BlockS.pos_Line);
  364.                 UPD2(thisvw->vw_BlockE.pos_Col, thisvw->vw_BlockE.pos_Line);
  365.         }
  366.         if(thisvw != curr_vw)
  367.         UPD(thisvw->vw_StartLine);
  368.     }
  369.     }
  370.     for(thismark = tx->tx_MarkChain; thismark; thismark = thismark->mk_Next)
  371.     {
  372.     UPD2(VPOS(thismark->mk_Pos).pos_Col, VPOS(thismark->mk_Pos).pos_Line);
  373.     }
  374.     UPD2(tx->tx_SavedCPos.pos_Col, tx->tx_SavedCPos.pos_Line);
  375.     UPD2(tx->tx_SavedWPos.pos_Col, tx->tx_SavedWPos.pos_Line);
  376.     UPD2(tx->tx_SavedBlockPos[0].pos_Col, tx->tx_SavedBlockPos[0].pos_Line);
  377.     UPD2(tx->tx_SavedBlockPos[1].pos_Col, tx->tx_SavedBlockPos[1].pos_Line);
  378.  
  379.     UPD2(tx->tx_ModStart.pos_Col, tx->tx_ModStart.pos_Line);
  380.     UPD2(tx->tx_ModEnd.pos_Col, tx->tx_ModEnd.pos_Line);
  381.  
  382. #undef UPD
  383. #undef UPD2
  384. }
  385.  
  386. /* These routines are called to recalculate the cursor's position on the
  387.    screen...  */
  388. static void
  389. resync_x(VW *vw)
  390. {
  391.     long offset;
  392.     calc_cursor_offset(vw);
  393.     offset = vw->vw_LastCursorOffset;
  394.     while((offset - vw->vw_StartCol) >= vw->vw_MaxX)
  395.     {
  396.     vw->vw_StartCol += vw->vw_XStep;
  397.     vw->vw_Flags |= VWFF_FORCE_REFRESH;
  398.     }
  399.     while(offset < vw->vw_StartCol)
  400.     {
  401.     vw->vw_StartCol -= vw->vw_XStep;
  402.     if(vw->vw_StartCol < 0)
  403.         vw->vw_StartCol = 0;
  404.     vw->vw_Flags |= VWFF_FORCE_REFRESH;
  405.     }
  406. }
  407.  
  408. static void
  409. resync_y(VW *vw)
  410. {
  411.     TX *tx = vw->vw_Tx;
  412.     long y = vw->vw_CursorPos.pos_Line - vw->vw_StartLine;
  413.     if(y < 0)
  414.     {
  415.     if(-y > vw->vw_YStep)
  416.         vw->vw_StartLine = vw->vw_CursorPos.pos_Line - (vw->vw_MaxY / 2);
  417.     else
  418.         vw->vw_StartLine -= vw->vw_YStep;
  419.     if(vw->vw_StartLine < 0)
  420.         vw->vw_StartLine = 0;
  421.     else if(vw->vw_StartLine >= tx->tx_NumLines)
  422.         vw->vw_StartLine = tx->tx_NumLines - 1;
  423.     }
  424.     else if(y >= vw->vw_MaxY)
  425.     {
  426.     if((vw->vw_MaxY + vw->vw_YStep) <= y)
  427.         vw->vw_StartLine = vw->vw_CursorPos.pos_Line - (vw->vw_MaxY / 2);
  428.     else
  429.         vw->vw_StartLine += vw->vw_YStep;
  430.     if(vw->vw_StartLine < 0)
  431.         vw->vw_StartLine = 0;
  432.     else if(vw->vw_StartLine >= tx->tx_NumLines)
  433.         vw->vw_StartLine = tx->tx_NumLines - 1;
  434.     /* Check for a `gap' at the bottom of the display */
  435.     if((tx->tx_NumLines >= vw->vw_MaxY)
  436.        && ((tx->tx_NumLines - vw->vw_StartLine) < vw->vw_MaxY))
  437.     {
  438.         vw->vw_StartLine = tx->tx_NumLines - vw->vw_MaxY;
  439.     }
  440.     }
  441. }
  442.  
  443. void
  444. resync_xy(VW *vw)
  445. {
  446.     if(vw->vw_Tx != vw->vw_LastRefTx)
  447.     /* kludge */
  448.     vw->vw_LastDisplayOrigin = vw->vw_DisplayOrigin;
  449.     resync_x(vw);
  450.     resync_y(vw);
  451. }
  452.  
  453. void
  454. set_start_col(VW *vw, long col)
  455. {
  456.     if(vw->vw_StartCol != col)
  457.     {
  458.     vw->vw_Flags |= VWFF_FORCE_REFRESH;
  459.     vw->vw_StartCol = col;
  460.     }
  461. }
  462.  
  463. void
  464. set_start_line(VW *vw, long line)
  465. {
  466.     long cline = vw->vw_StartLine;
  467.     if(line != cline)
  468.     {
  469.     long yord = vw->vw_CursorPos.pos_Line - cline;
  470.     vw->vw_StartLine = line;
  471. #if 0
  472.     /* This is done in vert_scroll() now; doing it here as
  473.        well means it's done twice!  */
  474.     if(!(vw->vw_Flags & VWFF_FORCE_REFRESH))
  475.     {
  476.         long diff = line - cline;
  477.         if((diff > 0) && (diff <= vw->vw_MaxScroll))
  478.         {
  479.         long ypos = vw->vw_MaxY - 1;
  480.         sys_scroll_vw(vw, diff);
  481.         redraw_lines(vw, cline + ypos, line + ypos + 1);
  482.         }
  483.         else if((diff < 0) && (diff >= -vw->vw_MaxScroll))
  484.         {
  485.         sys_scroll_vw(vw, diff);
  486.         redraw_lines(vw, line, cline);
  487.         }
  488.         else
  489.         vw->vw_Flags |= VWFF_FORCE_REFRESH;
  490.     }
  491.     else
  492.         vw->vw_Flags |= VWFF_FORCE_REFRESH;
  493. #endif
  494.     vw->vw_CursorPos.pos_Line = line + yord;
  495.     if(vw->vw_CursorPos.pos_Line >= vw->vw_Tx->tx_NumLines)
  496.         vw->vw_CursorPos.pos_Line = vw->vw_Tx->tx_NumLines - 1;
  497.     }
  498. }
  499.  
  500. /*
  501.  * This makes all views of this file have their cursor at the top of the
  502.  * file, it also refreshes each view.
  503.  */
  504. void
  505. reset_all_views(TX *tx)
  506. {
  507.     VW *thisvw;
  508.     for(thisvw = view_chain; thisvw; thisvw = thisvw->vw_Next)
  509.     {
  510.     if(thisvw->vw_Tx == tx)
  511.     {
  512.         thisvw->vw_CursorPos.pos_Col = 0;
  513.         thisvw->vw_CursorPos.pos_Line = 0;
  514.         thisvw->vw_StartCol = 0;
  515.         thisvw->vw_StartLine = 0;
  516.         thisvw->vw_BlockStatus = -1;
  517.         thisvw->vw_Flags |= VWFF_FORCE_REFRESH;
  518.         thisvw->vw_Flags &= ~VWFF_MESSAGE;
  519.         std_message(thisvw);
  520.     }
  521.     tx->tx_SavedCPos.pos_Col = 0;
  522.     tx->tx_SavedCPos.pos_Line = 0;
  523.     tx->tx_SavedWPos.pos_Col = 0;
  524.     tx->tx_SavedWPos.pos_Line = 0;
  525.     tx->tx_SavedBlockStatus = -1;
  526.     }
  527. }
  528.